<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=windows-1250">
  <meta name="generator" content="PSPad editor, www.pspad.com">
  <title></title>
  </head>
  <body style="padding: 0px 0px 0px 0px;">

<div  style="width:100%; background: #FAFAFF;  margin: 0px 0px -20px 0px; padding: 10px 10px 10px 10px;">
	<div style="width: 500px;  font-size: 12px; font-family: Arial; float: left;">
						<table border="0" style="font-size: 12px; font-family: Arial;">
            <tr>
            <td align="right">
            </td>
						<td>
            <input id="vartype" name="vartype" type="hidden" value="%"/> </td>
						</tr>

            <tr>
            <td align="right">
            Faint limit of equipment</td>
						<td><input id="faintlim" name="faintlim" size="5" type="text" value="7.5"/></td>
						</tr>
						
						<tr>
            <td align="right">
						Local standard time (integer hour from 0 to 24; e.g. 9PM = 21)</td>
						<td>
						<input id="loctime" name="loctime" size="5" type="text" value="22"/></td>
						</tr>
						
						<tr>
            <td align="right">
						Maximum hours east or west of meridian</td>
            <td>
            <input id="maxh" name="maxh" size="5" type="text" value="6"/></td>
            </tr>
            
            <tr>
            <td align="right">
						Declination (southernmost)</td>
						<td>
						<input id="mindec" name="mindec" size="5" type="text" value="-30"/></td>
						</tr>
						
						<tr>
            <td align="right">
						Declination (northernmost)</td>
						<td>
						<input id="maxdec" name="maxdec" size="5" type="text" value="90"/></td>
						</tr>
						</table>
            <input id="docsv" name="docsv" type="hidden" value="1" />
  <br>            
    <input type="button" 
            id="generatePlannerButton"
            value="Generate Observation Planner" />
  <br>            
  <br>            
	
  </div>
  <div style="align: center; font-family: Arial; font-size: 12px;">
    <span style="font-family: Arial; font-size: 24px;">Based on AAVSO's Basic Planner</span><br>
      <p>"Generate Observation Planner" fetches the data from AAVSO.org then filters it using the selected filters</p>
      <p>changing and filtering the results does not require fetching the data again</p>
      <p>variable types: M - mira, SR - all semiregulars, L - all irregulars, EB - all eclipsing binaries type B, RV - all RV Tauri types</p>
  </div>
    <div style="clear:both;">&nbsp;</div>
  
</div>

<br>

<div style="width:100%;  background: #FFFFFF;">
    <div style="font-size: 12px; font-family: Arial; width:140px; height: 100%; float: left; background: #FAFAFF; padding: 10px 10px 10px 10px;">

          <input type="button" id="applyFilter" value="Filter results by">
        <div style="margin: 20px 20px 0px 0px; ">
          <input type="checkbox" id="useMaxMagLimit" checked="1"> brighter at maximum then m = <input id="maxMagLimit" type="text" size="5" value="7.5"><br><br>
          <input type="checkbox" id="useMinMagLimit" checked="1"> brighter at minimum then m = <input id="minMagLimit" type="text" size="5" value="8.5"><br><br>
          <input type="checkbox" id="useAmplitude" checked="1"> with a variation of at least m = <input id="minAmplitude" type="text" size="5" value="0.5"><br><br>
          <input type="checkbox" id="useLastMonthObservations" checked="1"> with at most observations count during last month = <input id="lastMonthObservations" type="text" size="5" value="3"><br><br>
          <input type="checkbox" id="useLastMonthObservers" checked="1"> with at most observers count during last month = <input id="lastMonthObservers" type="text" size="5" value="3"><br><br>
          <input type="checkbox" id="useNotObservedForMoreThan" checked="1"> not observed since more than <input id="notObservedForMoreThan" type="text" size="5" value="15"> days<br><br>
          <input type="checkbox" id="useResultsVarType" checked="1"> variable type 
          <select name="resultsVarType" id="resultsVarType">
          </select>
          <br><br>
        </div>
        <br>
        <br>
    </div>
    
  <div style="height:100%; float: right;  margin: 20px 20px 20px 20px;">
    Results: <br>
    <table cellpadding="0" cellspacing="0" width="100%" style="border: solid 1px #000000;">
      <tr>
          <td width="4%"  style="border: solid 1px #000000;">No.</td>
          <td width="10%"  style="border: solid 1px #000000;">Name</td>
          <td width="10%" style="border: solid 1px #000000;">RA (<span id="raEpoch">2000</span>)</td>
          <td width="10%" style="border: solid 1px #000000;">DEC (<span id="decEpoch">2000</span>)</td>
          <td width="8%" style="border: solid 1px #000000;">Type</td>
          <td width="8%" style="border: solid 1px #000000;">Maximum</td>
          <td width="8%" style="border: solid 1px #000000;">Minimum</td>
          <td width="8%" style="border: solid 1px #000000;">Period</td>
          <td width="8%" style="border: solid 1px #000000;">Total observations</td>
          <td width="8%" style="border: solid 1px #000000;">observations count last 30 days</td>
          <td width="8%" style="border: solid 1px #000000;">observers count last 30 days</td>
          <td width="8%" style="border: solid 1px #000000;">Last observed</td>
      </tr>
    </table>
    <span id="resultsArea">
    </span>
    <span id="errorLog"></span>
  </div>

    <div style="clear:both;">&nbsp;</div>
    </div>

  </body>
</html>
<script type="text/javascript" language="JavaScript">


if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (obj, fromIndex) {
    if (fromIndex == null) {
        fromIndex = 0;
    } else if (fromIndex < 0) {
        fromIndex = Math.max(0, this.length + fromIndex);
    }
    for (var i = fromIndex, j = this.length; i < j; i++) {
        if (this[i] === obj)
            return i;
    }
    return -1;
  };
}

// define a class for results row

function resultsRow (rowString)
{
  this.err = "";
  this.ID = "";
  this.RA = 0;
  this.DEC = 0;
  this.RA_DEC_epoch = 2000;
  this.magAtMax = 0;
  this.magAtMin = 0;
  this.period = 0;
  this.totalObservationsCount = 0;
  this.lastMonthObservationsCount = 0;
  this.lastMonthObserversCount = 0;
  this.daysSinceLastObservation = 0;
  this.type = "&nbsp;";  
  
  this.magAmplitude = 0;

  var splitRow = rowString.split(",", 12);
  if (splitRow.length != 12)
  {
    this.err = "row format has changed.<br>";
    return;
  }
    // start parsing
  this.ID = splitRow[0];
  
  // RA
  var splitRA = splitRow[1].split(":", 3);
  if (splitRA.length != 3)
  {
    this.err += "column 1 does not have the format HOURS:MINUTES:SECONDS<br>";
    return;
  }
  
  if (splitRA[0].charAt(0) == '\"')
    splitRA[0] = splitRA[0].slice(1);
    
  var indexOfLastQuote = splitRA[2].indexOf ("\"");
  if (indexOfLastQuote > 0)
    splitRA[2] = splitRA[2].slice(0, indexOfLastQuote);
    
  // now convert it to full hour
  this.RA = (splitRA[0] * 3600 + splitRA[1] * 60 + splitRA[2] * 1) / 3600;
   

  // DEC
  var splitDec = splitRow[2].split(":", 3);
  if (splitDec.length != 3)
  {
    this.err += "column 2 does not have the format HOURS:MINUTES:SECONDS<br>";
    return;
  }
  
  if (splitDec[0].indexOf ("-") == 0)
    this.DEC = (splitDec[0] * 3600 - splitDec[1] * 60 - splitDec[2] * 1) / 3600;
  else
    this.DEC = (splitDec[0] * 3600 + splitDec[1] * 60 + splitDec[2] * 1) / 3600;

  this.type = splitRow[3];
  if (this.type == null || this.type.length == 0)
    this.type = "VAR";
  
  this.magAtMax = splitRow[4] * 1.0;
  this.magAtMin = splitRow[5] * 1.0;
  
  this.magAmplitude = this.magAtMin - this.magAtMax;
  if (this.magAmplitude < 0)
  {
    this.err += "wrong mangitudes provided; amplitude results negative.";
    return;
  }
  this.period = splitRow[7] * 1.0;
  this.totalObservationsCount = splitRow[8] * 1.0;
  this.lastMonthObservationsCount = splitRow[9] * 1.0;
  this.lastMonthObserversCount = splitRow[10] * 1.0;
  this.daysSinceLastObservation = splitRow[11] * 1.0;
}

function evaluateRow(row, filter)
{
    var conditionCounter = 0;
    if (filter != null && filter.conditions != null)
    {
      for (; conditionCounter < filter.conditions.length; conditionCounter++)
      {
          filter.conditions[conditionCounter] = filter.conditions[conditionCounter].replace(/ROW/g, "row");
          if (!eval (filter.conditions[conditionCounter]))
            return false;
      }
    }
    return (row.err == "");
}

function checkType (row, value)
{
  if (value == "*" || value == "%")
    return true;
    
  try{
    var pos = row.type.indexOf (value);
    if (pos < 0)
      return false;
      
    if (pos == 0)
      return true;
    
    if (pos > 0)
    {
      // check what precedes it. An alphabetical character means another type
      var codeBefore = row.charCodeAt(pos - 1) 
      if ( (97 <= codeBefore && codeBefore <= 122) || (65 <= codeBefore && codeBefore <= 90))
        return false;
    }
  }
  catch (err)
  {
    return false;
  }
  return false;
}  
 
  
var Planner = {

  _config: {
      plannerURL : "http://www.aavso.org/cgi-bin/obs_planner_web.pl",
      AAVSOFormControlNames : ["vartype", "faintlim", "loctime", 
                                "maxh", "mindec", "maxdec", "docsv"],
      filterControlsData : [ 
          {
            includeConditionControlName : "useMaxMagLimit",
            controlName: "maxMagLimit",
            conditionString : "ROW.magAtMax <= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useMinMagLimit",
            controlName: "minMagLimit",
            conditionString : "ROW.magAtMin <= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useAmplitude",
            controlName: "minAmplitude",
            conditionString : "ROW.magAmplitude >= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useLastMonthObservations",
            controlName: "lastMonthObservations",
            conditionString : "ROW.lastMonthObservationsCount <= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useLastMonthObservers",
            controlName: "lastMonthObservers",
            conditionString : "ROW.lastMonthObserversCount <= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useNotObservedForMoreThan",
            controlName: "notObservedForMoreThan",
            conditionString : "ROW.daysSinceLastObservation >= ",
            postConditionString : ""
          },
          {
            includeConditionControlName : "useResultsVarType",
            controlName: "resultsVarType",
            conditionString : " checkType (ROW, \"",
            postConditionString : "\")"
          }
                    
      ]
  },

  _unfilteredRows : [],
  
  _availableTypes : [],

  updateFilterConditions : function ()
  {
    Planner._filter.conditions = [];
    for (i = 0; i < Planner._config.filterControlsData.length; i++)
    {
      // check if the condition is included
        if (document.getElementById(Planner._config.filterControlsData[i].includeConditionControlName).checked)
        {
          // if that's true, then build a string as conditionString + value
          var condition = Planner._config.filterControlsData[i].conditionString + "" +
                          document.getElementById(Planner._config.filterControlsData[i].controlName).value +
                          Planner._config.filterControlsData[i].postConditionString;
          Planner._filter.conditions.push (condition);
        }
      // then add it in the conditions array of the filter
    }
  },
  
  _filter : {
    conditions : []
  },
  
  _buildQueryString : function ()
  {
      var queryString = "";
      
      for (i = 0; i < Planner._config.AAVSOFormControlNames.length - 1; i++)
      {
        queryString += Planner._config.AAVSOFormControlNames[i] + "=" +
                        document.getElementById (Planner._config.AAVSOFormControlNames[i]).value +
                        "&";                            
      }
      queryString += Planner._config.AAVSOFormControlNames[Planner._config.AAVSOFormControlNames.length - 1] + "=" +
                        document.getElementById (Planner._config.AAVSOFormControlNames[Planner._config.AAVSOFormControlNames.length - 1]).value;
                        
      return queryString;
  },
  
// function to fetch the CSV and return an array of the mentioned objects
  displayReport : function()
  {
    var url = Planner._config.plannerURL + "?" + Planner._buildQueryString();
    // XML HTTP request
    var xmlHttpReq = new XMLHttpRequest();
    xmlHttpReq.onreadystatechange = function()
    {
         if(xmlHttpReq.readyState == 4)
         {
             var docAsText =  xmlHttpReq.responseText;
             Planner._filterAndDisplayData (docAsText);
         }
    }
    xmlHttpReq.open("GET", url, true);
    xmlHttpReq.send(null);
    document.getElementById("resultsArea").innerHTML = "retrieving data ...";
    // in the _filterAndDisplayData() callback do the filtering
  },
  
// function to take the array,  a filter and return a filtered array
  _filterRawData : function (rawData)
  {
    Planner._availableTypes = ["*", "E", "I", "L", "M", "SR"];

    var selectCtrl = document.getElementById ("resultsVarType");
    selectCtrl.options.length = 0;
  
    Planner._unfilteredRows = [];
    
    // split the raw data in lines
    var splittedRawData = rawData.split ("\n");
    // first line is the header. Try to extract the epoch
    var epoch = 2000;
    var splittedFirstRow = splittedRawData[0].split(",", 12);
    if (splittedFirstRow.length >= 2)
    {
      var RA = splittedFirstRow[1];
      var indexOfLeftParam = RA.indexOf ("(");
      var indexOfRightParam = RA.indexOf (")");
      if (indexOfLeftParam > 0 && indexOfRightParam > 0)
        epoch = 2000; // Math.floor (1.0 * RA.substring (indexOfLeftParam + 1, indexOfRightParam - indexOfLeftParam));
    }
    
    var firstError = true;
    // then keep building objects.
    for (i = 1; i < splittedRawData.length; i++)
    {
      var rowObj = new resultsRow (splittedRawData [i]);
      rowObj.RA_DEC_epoch = epoch;
      if (rowObj.err != "" && i < splittedRawData.length - 1)
      {
        if (firstError)
        {
            document.getElementById ("errorLog").innerHTML = "The following errors were encountered: <br>";
            firstError = false;
        }
        document.getElementById ("errorLog").innerHTML = document.getElementById ("errorLog").innerHTML  + "&nbsp;&nbsp;&nbsp;&nbsp;" + rowObj.ID + rowObj.err;
      }
      else
      {
        Planner._unfilteredRows.push (rowObj);
        var currentRowType = rowObj.type;
        if(currentRowType != "&nbsp;" && Planner._availableTypes.indexOf(currentRowType) == -1)
            Planner._availableTypes.push (currentRowType);
      }
    }
    
    // now, set the options
    for (i = 0; i < Planner._availableTypes.length; i++)
      if (Planner._availableTypes[i].length <= 8)
        selectCtrl.options[selectCtrl.options.length] = new Option (Planner._availableTypes[i], Planner._availableTypes[i]);
    
  },
  
  _filterRows : function ()
  {
      var filteredListOfRowObjects = [];
      for (i = 0; i < Planner._unfilteredRows.length; i++)
      if ( evaluateRow (Planner._unfilteredRows[i], Planner._filter))
        filteredListOfRowObjects.push(Planner._unfilteredRows[i]);
        
      return filteredListOfRowObjects;
  },
  
  _filterAndDisplayData : function (rawData)
  {
    Planner._filterRawData (rawData);
    Planner.refreshFilteredData ();
  },
  
  _convertDoubleToSexa : function (doubleValue, arrayOfSymbols)
  {
      var value = Math.abs(doubleValue);

      var degs = Math.floor (value);
      var mins = Math.floor((value - degs) * 60);
      var sec = Math.floor((value - degs - mins / 60)*3600);

      var converted = "" + degs + "" + arrayOfSymbols[0] +
                        mins + "" + arrayOfSymbols[1] +
                        sec + "" + arrayOfSymbols[2];
      
      if (doubleValue < 0)
          converted = "-" + converted;
          
      return converted;
  },
  
  refreshFilteredData : function ()
  {
    Planner.updateFilterConditions();
    var filteredData = Planner._filterRows();
    var htmlCode = "<table border=\"1\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" style=\"border: solid 1px #000000;\">";
    for (i = 0; i < filteredData.length; i++)
    {
      if (i%2 == 0)
        htmlCode += "<tr>";
      else
        htmlCode += "<tr style=\"background: #FAFAFF;\">";
      htmlCode += 
                    "<td width=\"4%\" style=\"border: solid 1px #000000;\">" + (i+1) + "</td>" +
                    "<td width=\"10%\" style=\"border: solid 1px #000000;\">" + filteredData[i].ID + "</td>" +
                    "<td width=\"10%\" style=\"border: solid 1px #000000;\">" + Planner._convertDoubleToSexa (filteredData[i].RA, ["h", "m", "s"]) + "</td>" +
                    "<td width=\"10%\" style=\"border: solid 1px #000000;\">" + Planner._convertDoubleToSexa (filteredData[i].DEC, ["&ordm;", "\'", "\'\'"]) + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].type + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].magAtMax + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].magAtMin + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].period + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].totalObservationsCount + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].lastMonthObservationsCount + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].lastMonthObserversCount + "</td>" +
                    "<td width=\"8%\" style=\"border: solid 1px #000000;\">" + filteredData[i].daysSinceLastObservation + "</td>" +
                  "</tr>";
    }
    htmlCode += "</table>";
    // set the html code as InnerHTML 
    document.getElementById("resultsArea").innerHTML = htmlCode;
  },
  
  // &ordm;
  init : function ()
  {
      // associate the submit button
      document.getElementById ("generatePlannerButton").onclick = function () { Planner.displayReport(); };
      // associate the filter button
      document.getElementById ("applyFilter").onclick = function () { Planner.refreshFilteredData(); };
      // associate the filter controls
      for (i = 0; i < Planner._config.filterControlsData.length; i++)
      {
          document.getElementById (Planner._config.filterControlsData[i].includeConditionControlName).onchange = Planner.updateFilterConditions;
          document.getElementById (Planner._config.filterControlsData[i].controlName).onchange = Planner.updateFilterConditions;
      }      
  }
  
}; 

Planner.init();

// callbacks for controls - on change alter the filter profile


</script>
